import React ,{Component} from 'react'
import {
  Form,
  Icon,
  Input,
  Button,
 // message
} from 'antd'
import {connect } from 'react-redux'
import {login} from '../../redux/actions'
import './login.less'
import logo from '../../assets/images/logo.png'
// 默认暴露  不要 { }
//import { reqLogin } from '../../api'
//import memoryUtils from '../../utils/memoryUtils'
//import storageUtils  from '../../utils/storageUtils'
import { Redirect } from 'react-router-dom';
const Item = Form.Item // 写在 import 后面

// 登录路由组件
class Login extends Component{
     handleSubmit =(event) =>{
      event.preventDefault()
        // 得到form对象
      // const form = this.props.form
      // // 获取表单项的输入数据
      // const values = form.getFieldsValue()
      // console.log('handleSubmit()', values)
      this.props.form.validateFields(async (err,values)=>{
          if(!err){
             console.log('提交登录',values);
             const {username,password} = values
            //  try{
            //   const res = await reqLogin(username,password)
            //   console.log('res',res);
            //  }catch(err){
            //   console.log('err',err);
            //  }

            // const result = await reqLogin(username,password)
            // //console.log('res',res);
            // //const result = res.data;
            // if(result.status===0){
            //   message.success('登录成功')
            //   // 保存用户信息
            //   const user = result.data;
            //   memoryUtils.user = user;
            //   storageUtils.saveUser(user)
            //   // 不要回退  用 replace   需要回退 用 push
            //   this.props.history.replace('/home')
            // }else{
            //   message.error(result.msg)
            // }
            // 调用异步 action 函数  发送登录 异步请求  有了结果 更新状态
            this.props.login(username,password)

          }else{
             console.log('提交失败');
          }
      })

     }

         /*
  对密码进行自定义验证
  */
  /*
   用户名/密码的的合法性要求
     1). 必须输入
     2). 必须大于等于4位
     3). 必须小于等于12位
     4). 必须是英文、数字或下划线组成
    */
     validatePwd = (rule, value, callback) => {
      console.log('validatePwd()', rule, value)
      if(!value) {
        callback('密码必须输入')
      } else if (value.length<4) {
        callback('密码长度不能小于4位')
      } else if (value.length>12) {
        callback('密码长度不能大于12位')
      } else if (!/^[a-zA-Z0-9_]+$/.test(value)) {
        callback('密码必须是英文、数字或下划线组成')
      } else {
        callback() // 验证通过
      }
      // callback('xxxx') // 验证失败, 并指定提示的文本  xxxx
      }

     render(){

      //  如果 用户已经登录   自动跳到 管理页码  地址栏输入 /login  也会跳 管理页面
      //const user = memoryUtils.user;
      const user = this.props.user;
      if(user && user._id){
         return <Redirect to="/home" />
      }
      const errorMsg = user.errorMsg

      const from = this.props.form;
      const { getFieldDecorator} = from

      return (<div className="login">
           <header className="login-header">
              <img src={logo} alt="logo" />
              <h1>React项目: 后台管理系统</h1>
           </header>
           <section className="login-content">
           <div className={errorMsg ? 'error-msg show' : 'error-msg'}>{errorMsg}</div>
           <h2>用户登陆</h2>
              <Form onSubmit={this.handleSubmit} className="login-form">
                <Item>
                  {
                    /*
                  用户名/密码的的合法性要求
                    1). 必须输入
                    2). 必须大于等于4位
                    3). 必须小于等于12位
                    4). 必须是英文、数字或下划线组成
                    */
                  }
                  {
                    getFieldDecorator('username', { // 配置对象: 属性名是特定的一些名称
                      // 声明式验证: 直接使用别人定义好的验证规则进行验证
                      rules: [
                        { required: true, whitespace: true, message: '用户名必须输入' },
                        { min: 4, message: '用户名至少4位' },
                        { max: 12, message: '用户名最多12位' },
                        { pattern: /^[a-zA-Z0-9_]+$/, message: '用户名必须是英文、数字或下划线组成' },
                      ],
                      initialValue: 'admin', // 初始值
                    })(
                      <Input
                        prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
                        placeholder="用户名"
                      />
                    )
                  }
                </Item>
                <Form.Item>
                  {
                    getFieldDecorator('password', {
                      rules: [
                        {
                          validator: this.validatePwd
                        }
                      ],
                      initialValue: 'admin', // 初始值
                    })(
                      <Input
                        prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />}
                        type="password"
                        placeholder="密码"
                      />
                    )
                  }
    
                </Form.Item>
                <Form.Item>
                  <Button type="primary" htmlType="submit" className="login-form-button">
                    登陆
                  </Button>
                </Form.Item>
              </Form>
           </section>
        </div>)
    }
}

// 组件是类型   标签是 类型的 某一个实例 


// Login   被包装组件 (子组件)   WrapLogin   包装组件(父组件)
const WrapLogin = Form.create()(Login)
export default connect(
  state=> ({ user:state.user}),
   {login}
)(WrapLogin);

/*
1. 高阶函数
    1). 一类特别的函数  满足一个就是高阶函数
        a. 接受函数类型的参数
        b. 返回值是函数
    2). 常见
        a. 定时器: setTimeout()/setInterval()
        b. Promise: Promise(() => {}) then(value => {}, reason => {})
        c. 数组遍历相关的方法: forEach()/filter()/map()/reduce()/find()/findIndex()
        d. 函数对象的bind()
        e. Form.create()() / getFieldDecorator()()
    3). 高阶函数更新动态, 更加具有扩展性

2. 高阶组件
    1). 本质就是一个函数
    2). 接收一个组件(被包装组件), 返回一个新的组件(包装组件), 包装组件会向被包装组件传入特定属性
    3). 作用: 扩展组件的功能
    4). 高阶组件也是高阶函数: 接收一个组件函数, 返回是一个新的组件函数
 */
/*
包装Form组件生成一个新的组件: Form(Login)
新组件会向Form组件传递一个强大的对象属性: form
 */

/*
1. 前台表单验证
2. 收集表单输入数据
 */

/*
async和await
1. 作用?
   简化promise对象的使用: 不用再使用then()来指定成功/失败的回调函数
   以同步编码(没有回调函数了)方式实现异步流程
2. 哪里写await?
    在返回promise的表达式左侧写await: 不想要promise, 想要promise异步执行的成功的value数据
3. 哪里写async?
    await所在函数(最近的)定义的左侧写async
 */
